package com.vagavaga.tx;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;


public abstract class AbstractModule  {
    /**
     * Map containing sql statements from property files. This is a way to
     * cache sql statements.
     */
    private static Map<Class<? extends AbstractModule>, Properties> sql = new WeakHashMap<Class<? extends AbstractModule>, Properties>();

    /**
     * Allowes subsclases to access sql contained in property file with the
     * same name as implementation class and residing in the same directory.
     * <p>If for example FooImpl class extends JDBCModule and implements Foo
     * interface than FooImpl can read sql statements from file named:
     * FooImpl.properties witch resides in the same package as FooImpl class.
     * <p>Subclasses are encouraged to use this functionality since it alowes
     * externalization of SQL statements from code, witch leads to easy
     * supporting of multiple database dialects.
     *
     * @param key Key under witch sql statemnent is in property file.
     * @return SQL statement, or null if no statement under key is found.
     */
    protected String getSQL(String key) {
        return (String) loadSQL().get(key);
    }

    /**
     * Method that actualy loads property file with SQL statements into
     * memory. For performance reasons implementation caches loaded statements
     * into WeakHashMap.
     * @return Map instance containing all statments indexed by key from
     * property file.
     */
    private final Map loadSQL() {
        Class<? extends AbstractModule> cls = getClass();
        Map map;
        synchronized (sql) {
            if (!sql.containsKey(cls)) {
                String fullName = cls.getName();
                String name = fullName;
                int dot = fullName.lastIndexOf('.');
                if (dot > 0) {
                    name = fullName.substring(dot + 1);
                }

                Properties props = new Properties();
                InputStream is = cls.getResourceAsStream(name +
                        "_sql" + ".properties");
//                if (is == null) {
//                    is = cls.getResourceAsStream(name + ".properties");
//                }

                if (is != null) {
                    try {
                        props.load(is);
                    } catch (IOException ex) {
                        /** @todo LOG ERROR */
                    }
                }
                sql.put(cls, props);
            }
            map = sql.get(cls);
        }
        return map;
    }
}
